Python 高级2

匹配字符串开头或结尾

检查字符串开头或结尾的一个简单方法是使用 str.startswith() 或者是 str.endswith() 方法 ,这个方法中必须要输入一个元组作为参数。 如果你恰巧有一个 list 或者 set 类型的选择项, 要确保传递参数前先调用 tuple() 将其转换为元组类型

1
2
3
choices = ['http:', 'ftp:']
url = 'http://www.python.org'
print(url.startswith(tuple(choices))) # True

还可以使用 fnmatch 模块来进行字符串的匹配,fnmatch 模块提供了两个函数 fnmatch()fnmatchcase() 传入要匹配的

1
2
3
4
5
6
7
8
9
10
11
from fnmatch import fnmatch, fnmatchcase

print(fnmatch("text.py", "?t.py")) # False
print(fnmatch("text.py", "*t.py")) # True

# fnmatch 在不同操作系统下结果不同
print(fnmatch('foo.txt', '*.TXT')) # win True
print(fnmatch('foo.txt', '*.TXT')) # mac False

# 如果要让结果保持一致,就使用
print(fnmatchcase('foo.txt', '*.TXT')) # False

字符串匹配和搜索

1
2
3
4
5
text = 'yeah, but no, but yeah, but no, but yeah'

print(text.startswith('yeah')) # True
print(text.endswith('yeah')) # True
print(text.find("no")) # 10

正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'

import re

# 使用 re.compile() 编译正则表达式字符串, 然后使用 match() , findall() 或者 finditer() 等方法
datepat = re.compile(r"\d+/\d+/\d+")

print(datepat.match(text)) # match 只会从字符串开始去匹配,所以结果为 none
print(datepat.findall(text)) # ['11/27/2012', '3/13/2013']

# 以迭代方式返回匹配的内容
for x in datepat.finditer(text):
print(x.group())
# 11/27/2012
# 3/13/2013

如果你仅仅是做一次简单的文本匹配/搜索操作的话,可以略过编译部分,直接使用 re 模块级别的函数 。但是需要注意的是,如果你打算做大量的匹配和搜索操作的话,最好先编译正则表达式,然后再重复使用它。 模块级别的函数会将最近编译过的模式缓存起来,因此并不会消耗太多的性能

字符串搜索和替换

对于简单的字面模式,直接使用 str.replace() 方法即可。对于复杂的模式,可以使用 re 模块中的 sub() 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'

import re

# 第一个参数是被匹配的模式,第二个参数是替换模式
print(re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text))
# Today is 2012-11-27. PyCon starts 2013-3-13.

# 使用命名分组
print(re.sub(r'(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)', r'\g<year>-\g<month>-\g<day>', text))
# Today is 2012-11-27. PyCon starts 2013-3-13.

# 使用 compile 编译
datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
print(datepat.sub(r'\3-\1-\2', text))

# 使用回调函数
def callback(match):
print(match.group())
datepat.sub(callback, text)

删除字符串中不需要的字符

1
2
3
4
5
6
7
8
9
10
s = ' hello world \n'

print(s.strip()) # 去除两边空格和换行
print(s.lstrip()) # 去除左边空格和换行
print(s.rstrip()) # 去除右边空格和换行

t = '-----hello====='
print(t.strip("-=")) # hello
print(t.lstrip("-")) # hello=====
print(t.rstrip("=")) # -----hello
1
2
3
4
5
6
7
s = ' hello     world \n'

import re

print(s.strip()) #hello world
print(s.replace(' ', '')) #helloworld
print(re.sub('\s+', ' ', s)) # hello world

字符串对齐

1
2
3
4
5
6
7
text = 'Hello World'

print(text.ljust(20)) # Hello World
print(text.rjust(20)) # Hello World
print(text.rjust(20, "*")) # *********Hello World
print(text.ljust(20, "*")) # Hello World*********
print(text.center(20, "*")) # ****Hello World*****

拼接字符串

当我们使用加号(+)操作符去连接大量的字符串的时候是非常低效率的, 因为加号连接会引起内存复制以及垃圾回收操作。应该多使用 join() 和 生成器

1
2
data = ['ACME', 50, 91.1]
print(','.join(str(d) for d in data)) # 使用生成器,ACME,50,91.1

指定列宽格式化字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
s = "Look into my eyes, look into my eyes, the eyes, the eyes, \
the eyes, not around the eyes, don't look around the eyes, \
look into my eyes, you're under."

import textwrap

print(textwrap.fill(s, 40))
"""
Look into my eyes, look into my eyes,
the eyes, the eyes, the eyes, not around
the eyes, don't look around the eyes,
look into my eyes, you're under.
"""

print(textwrap.fill(s, 40, initial_indent=" "))
"""
Look into my eyes, look into
my eyes, the eyes, the eyes, the eyes,
not around the eyes, don't look around
the eyes, look into my eyes, you're
under.
"""

print(textwrap.fill(s, 40, subsequent_indent=" "))
"""
Look into my eyes, look into my eyes,
the eyes, the eyes, the eyes,
not around the eyes, don't
look around the eyes, look
into my eyes, you're under.
"""